﻿using MotionCS.Alarm;
using MotionCS.Controller;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using MotionCS.Helper;
namespace MotionCS.Controller
{
    public class Pci9014Axis : IAxis
    {
        /// <summary>
        /// 轴配置参数
        /// </summary>
        private AxisConfi config;
        public AxisConfi Config { get => config; }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="axisConfi"></param>
        public Pci9014Axis(AxisConfi axisConfi)
        {
            config = axisConfi;
            InitConfi();
        }

        /// <summary>
        /// 初始化轴配置
        /// </summary>
        private void InitConfi()
        {
            Pci9014Api.set_pls_outmode(config.Axis, config.OutMode);
            Pci9014Api.set_pls_iptmode(config.Axis, config.IptMode);
            if (config.HomeMode != -1)
            {
                Pci9014Api.home_config(config.Axis, config.HomeMode, 0, 0);
                Pci9014Api.set_el_level(config.Axis, config.ElLevel);
            }
            SetMualSpeed();
        }
        /// <summary>
        /// 设置手动速度
        /// </summary>
        public void SetMualSpeed()
        {
            Pci9014Api.set_s_profile(config.Axis, config.StartSpeed * config.OutUnit, config.MualSpeed * config.OutUnit, config.MualAccel * config.OutUnit, config.MualDecel * config.OutUnit, config.Sramp);
        }
        /// <summary>
        /// 设置自动速度
        /// </summary>
        public void SetAutoSpeed()
        {

         
            Pci9014Api.set_t_profile(config.Axis, config.AutoSpeed * config.OutUnit / 10, config.AutoSpeed * config.OutUnit, config.AutoAccel * config.OutUnit, config.AutoDecel * config.OutUnit);
      
        }

        public void SetAutoSpeed2()
        {
            Pci9014Api.set_t_profile(config.Axis, config.StartSpeed * config.OutUnit / 2, config.MualSpeed * config.OutUnit/4, config.AutoAccel * config.OutUnit / 3, config.AutoDecel * config.OutUnit);


          //  Pci9014Api.set_t_profile(config.Axis, config.StartSpeed * config.OutUnit / 4, config.StartSpeed * config.OutUnit / 2, config.AutoAccel * config.OutUnit / 3, config.AutoDecel * config.OutUnit);
        }



        /// <summary>
        /// 进入回零速度
        /// </summary>
        public void SetHomeSpeed()
        {
            Pci9014Api.set_s_profile(config.Axis, config.HomeSpeedH * config.OutUnit, config.HomeSpeedH * config.OutUnit, config.HomeAccel * config.OutUnit, config.HomeDecel * config.OutUnit, config.Sramp);
        }
        /// <summary>
        /// 获取轴运行状态
        /// </summary>
        /// <returns>true-停止 false-运动中</returns>
        public bool IsCheckDone()
        {
            uint iValue = 0;
            Pci9014Api.get_motion_status(config.Axis, ref iValue);
            return iValue == 0;
        }
        /// <summary>
        /// 运动到绝对点
        /// </summary>
        /// <param name="fdis"></param>
        public int MoveAbs(double fdis)
        {
            if (config.HomeMode != -1)
            {
                if (fdis > config.FsLimit ||  fdis < config.RsLimit)
                {
                    return -1;
                }

                Pci9014Api.pmove(config.Axis, (int)(fdis * config.OutUnit), 1, 2);
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 运动到相对点
        /// </summary>
        /// <param name="fdis"></param>
        public int MoveRel(double fdis)
        {
            if (config.HomeMode != -1)
            {
                double curpos = 0.0f;
                GetPositionUnit(ref curpos);
                double rel = config.MoveDir == 0 ? fdis : -fdis;
                double dis = curpos + rel;
                if (dis > config.FsLimit || dis < config.RsLimit)
                {
                    return -1;
                }

                Pci9014Api.pmove(config.Axis, (int)(rel * config.OutUnit), 0, 2);
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 前向运动
        /// </summary>
        /// <param name="dir"></param>
        public int MoveForward()
        {
            int dir = config.MoveDir == 0 ? 1 : 0;
            Pci9014Api.vmove(config.Axis, dir, 2);
            if (config.HomeMode != -1)
            {
                SoftLimitTask();
            }
            return 0;
        }
        /// <summary>
        /// 后向运动
        /// </summary>
        public int MoveBackward()
        {
            int dir = config.MoveDir == 0 ? 0 : 1;
            Pci9014Api.vmove(config.Axis, dir, 2);
            if (config.HomeMode != -1)
            {
                SoftLimitTask();
            }
           
            return 0;
        }
        /// <summary>
        /// 停止运动
        /// </summary>
        public int MoveStop()
        {

            if (!IsCheckDone())
            {
                Pci9014Api.stop(config.Axis, 0);
            }

            return 0;
        }
        /// <summary>
        /// 急停运动
        /// </summary>
        public int EmgStop()
        {
            if (!IsCheckDone())
            {
                Pci9014Api.stop(config.Axis, 1);
            }
            return 0;
        }
        /// <summary>
        /// 回零运动
        /// </summary>
        public int MoveHome()
        {
            if (config.HomeMode != -1)
            {
                SetHomeSpeed();
                Pci9014Api.home_move(config.Axis, config.HomeDir);
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 软件限位任务
        /// </summary>
        private void SoftLimitTask()
        {
            double pos = 0.0;

            Task.Run(() =>
            {
                while (!IsCheckDone())
                {
                    GetPositionUnit(ref  pos);
                    if (pos > config.FsLimit || pos < config.RsLimit)
                    {
                        EmgStop();
                        break;
                    }
                    ThreadHelper.Delay(1);
                }
            });
        }
        /// <summary>
        /// 是否到位
        /// </summary>
        /// <returns>true 到位 flase 未到位</returns>
        public bool IsInp()
        {
            uint piVal = 0;
            int cardno = config.Axis / 4;
            if (config.Inp != -1)
            {
                Pci9014Api.get_di_bit(cardno, (uint)config.Inp, ref piVal);
            }
      
            return piVal == 0;
        }
        /// <summary>
        /// 是否回零完成
        /// </summary>
        /// <returns>false 回零中 true 回零成功 </returns>
        public bool IsHomeFinish()
        {
            uint iValue = 0;
            Pci9014Api.get_motion_status(config.Axis, ref iValue);
            return iValue == 0;
        }
        /// <summary>
        /// 设置当前位置
        /// </summary>
        /// <param name="dpos"></param>
        public int SetPositionUnit(double dpos)
        {
            if (config.Axis != -1)
            {
                Pci9014Api.set_pos(config.Axis, 0, (int)(dpos * config.OutUnit));
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 获取当前位置
        /// </summary>
        /// <returns></returns>
        public int GetPositionUnit(ref double dpos)
        {
            if (config.Axis != -1)
            {
                int pos = 0;
                Pci9014Api.get_pos(config.Axis, 0, ref pos);
                dpos = (float)pos / config.OutUnit;
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 设置编码器反馈位置
        /// </summary>
        /// <param name="mpos"></param>
        public int SetEncoderUnit(double mpos)
        {
            if (config.Axis != -1)
            {
                Pci9014Api.set_pos(config.Axis, 1, (int)(mpos * config.IptUnit));
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 获取编码器反馈位置
        /// </summary>
        /// <param name="mpos"></param>
        public int GetEncoderUnit(ref double mpos)
        {
            if (config.Axis != -1)
            {
                int pos = 0;
                Pci9014Api.get_pos(config.Axis, 1, ref pos);
                mpos = (float)pos / config.IptUnit;
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 轴运动速度
        /// </summary>
        /// <param name="speed"></param>
        public int GetVpSpeed(ref double speed)
        {
            double dspd = 0.0;
            Pci9014Api.get_current_speed(config.Axis, ref dspd);
            speed = (float)dspd / config.OutUnit;
            return 0;
        }
        /// <summary>
        /// 回零中
        /// </summary>
        /// <returns>false-回零中 true-回零成功</returns>
        public bool GetHomeStatus()
        {
            //int piValue = 0;
            //ControlApi.AxisGetStatus(Axis, ref piValue);

            //if ((piValue & 0x40) == 0x40)
            //{
            //    return false;
            //}
            //else
            //{
            //    return true;
            //}

            return true;
        }
        /// <summary>
        /// 获取轴状态
        /// </summary>
        /// <returns></returns>
        public MotorStatus GetStatus()
        {
            MotorStatus motorStatus = new MotorStatus();
            UInt32 status = 0;
            Pci9014Api.get_io_status(config.Axis, ref status);

            motorStatus.ElPosLimit = (status & 0x01) == 0x01;
            motorStatus.ElNegLimit = (status & 0x02) == 0x02;

            if (config.Alm != -1)
            {
                int cardno = (config.Alm % 1000) / 16;
                uint index = (uint)((config.Alm % 1000) % 16);
                uint value = 0;
                Pci9014Api.get_di_bit(cardno, index, ref value);

                motorStatus.ServoAlarm = config.AlmLevel == 0 ? value == 1 : value == 0;
            }

            return motorStatus;
        }
        /// <summary>
        /// 是否在原点
        /// </summary>
        /// <returns></returns>
        public bool IsHomeInOn()
        {
            UInt32 status = 0;
            Pci9014Api.get_io_status(config.Axis, ref status);
            return (status & 0x4) == 0x4;
        }
        /// <summary>
        /// 是否触发硬件负限位
        /// </summary>
        /// <returns>false 未触发 true 触发</returns>
        public bool IsElRevLimit()
        {
            UInt32 status = 0;
            Pci9014Api.get_io_status(config.Axis, ref status);
            return (status & 0x2) == 0x2;
        }
        /// <summary>
        /// 是否触发硬件正限位
        /// </summary>
        /// <returns>false 未触发 true 触发</returns>
        public bool IsElFwdLimit()
        {
            UInt32 status = 0;
            Pci9014Api.get_io_status(config.Axis, ref status);
            return (status & 0x1) == 0x1;
        }
        /// <summary>
        /// 获取轴IO状态
        /// </summary>
        /// <returns></returns>
        public uint GetIoStatus()
        {
            UInt32 status = 0;
            Pci9014Api.get_io_status(config.Axis, ref status);

            return status;
        }
        /// <summary>
        /// 是否驱动器报警
        /// </summary>
        /// <returns>false 未报警 true 报警</returns>
        public bool IsAlarm()
        {
           

            return false;
        }

        /// <summary>
        /// 伺服使能
        /// </summary>
        public void SevonEnable()
        {
            
        }
        /// <summary>
        /// 伺服失能
        /// </summary>
        public void SevonDisable()
        {
            
        }
        /// <summary>
        /// 复位使能
        /// </summary>
        public void ResetEnable()
        {
            
        }
        /// <summary>
        /// 复位失能
        /// </summary>
        public void ResetDisable()
        {
           
        }
    }
}
